package cn.itcast.dtx.txmsgdemo.bank1.service.impl;

import cn.itcast.dtx.txmsgdemo.bank1.dao.AccountInfoDao;
import cn.itcast.dtx.txmsgdemo.bank1.model.AccountChangeEvent;
import cn.itcast.dtx.txmsgdemo.bank1.service.AccountInfoService;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.concurrent.ConcurrentHashMap;

/**
 * @author zh_o
 * @date 2020-11-13
 */
@Service
@Slf4j
public class AccountInfoServiceImpl implements AccountInfoService {

    @Autowired
    private AccountInfoDao accountInfoDao;

    @Autowired
    private ObjectMapper json;

    @Autowired
    private RocketMQTemplate rt;

    /**
     * 向 mq 发送转账消息
     * @param accountChangeEvent 消息对象
     */
    @Override
    public void sendUpdateAccountBalance(AccountChangeEvent accountChangeEvent) throws Exception {
        // 将消息对象转为 JSON
        ConcurrentHashMap<String, Object> map = new ConcurrentHashMap<>();
        map.put("accountChange", accountChangeEvent);
        String jsonStr = json.writeValueAsString(map);
        // 构建消息
        Message<String> msg = MessageBuilder.withPayload(jsonStr).build();
        // 发送事务消息
        rt.sendMessageInTransaction("tx_msg", msg, null);
    }

    /**
     * 新账户，扣减金额
     * @param accountChangeEvent 消息对象
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void doUpdateAccountBalance(AccountChangeEvent accountChangeEvent) {
        // 幂等判断
        if (accountInfoDao.isExistTx(accountChangeEvent.getTxNo()) > 0) {
            return;
        }
        // 扣除金额
        accountInfoDao.updateAccountBalance(accountChangeEvent.getAccountNo(),
                accountChangeEvent.getAmount() * -1);
        // 添加事务日志
        accountInfoDao.addTx(accountChangeEvent.getTxNo());
    }
}
